package com.up.jiasai.modules.oauth.service;

import com.alibaba.fastjson.JSONObject;
import com.up.vms.application.base.auth.UserSession;
import com.up.vms.application.base.exception.SysException;
import com.up.vms.application.base.http.HttpResult;
import com.up.vms.application.base.http.HttpUtils;
import com.up.vms.application.base.utils.JsonUtils;
import com.up.jiasai.cache.CacheService;
import com.up.vms.application.constants.Constants;
import com.up.vms.domain.op.entity.UserDO;
import com.up.vms.domain.module.SycUserInfo;
import com.up.vms.application.service.UserService;

import com.up.vms.application.common.utils.UnionUtils;
import com.up.vms.infrastructure.cache.RedisCacheManager;
import com.up.vms.infrastructure.util.CommonUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class OauthLoginService {
    protected final Logger logger = LoggerFactory.getLogger(OauthLoginService.class);
    private static final int ONE_DAY_SECOND = 86400;
    @Autowired
    CacheService cacheService;
    @Value("${oauth.clientId}")
    private String clientId;
    @Value("${oauth.clientSecret}")
    private String clientSecret;
    @Value("${oauth.responseType}")
    private String responseType;
    @Value("${yghApp.url}")
    private String yghAppUrl;
    @Value("${oauth.accessTokenKey}")
    private String accessTokenKey;


    @Autowired
    private RedisCacheManager redisCacheManager;
    @Autowired
    private UserService userService;

    /**
     * OAuth 获取用户信息
     *
     * @param code        在这里的code相当于用户的身份信息
     * @param accessToken 这个token相当于第三方应用的的身份信息
     * @return openId 这个openId是唯一不变的
     */
    public String getOauthUserInfo(String code, String accessToken) throws SysException {
        String userInfoHttpResult = null;
        Map userInfoMaps = new HashMap(5);
        userInfoMaps.put("code", code);
        userInfoMaps.put("accessToken", accessToken);
        String url = this.yghAppUrl + "/oauth/userInfo?" + HttpUtils.urlEncode(userInfoMaps);
        try {
            userInfoHttpResult = HttpUtils.get(url).makeHtml("utf-8");
        } catch (Exception e) {
            logger.error("获取用户信息异常", e);
            e.printStackTrace();
            throw new SysException(e.getMessage());
        }
        if (StringUtils.isEmpty(userInfoHttpResult)) {
            logger.error("[请求接口] OAuth获取用户信息，返回JSON解析异常");
            throw new SysException("登录返回信息:''");
        }
        JSONObject userInfoJsonObject = JsonUtils.asJSONObject(userInfoHttpResult);

        //调试代码
        //logger.debug("0、请求地址: "+url);
        //logger.debug("1、请求获取的用户信息: "+userInfoHttpResult);

        String success = userInfoJsonObject.getString("success");
        // 判断是否返回用户信息 判断是否为accessToken失效
        if ("false".equals(success)) {
            String errorCode = userInfoJsonObject.getString("errorCode");
            if ("100002".equals(errorCode)) {
                accessToken = getOauthAccessToken();
                if (StringUtils.isEmpty(accessToken)) {
                    throw new SysException("[请求异常] OAuth获取accessToken为空");
                }
                userInfoMaps.put("accessToken", accessToken);
                try {
                    userInfoHttpResult = HttpUtils.get(url).makeHtml("utf-8");
                    if (StringUtils.isEmpty(userInfoHttpResult)) {
                        logger.warn("[请求异常] OAuth获取用户信息，返回JSON解析异常");
                        throw new SysException("[请求异常] OAuth获取用户信息为空");
                    }
                    userInfoJsonObject = JsonUtils.asJSONObject(userInfoHttpResult);
                } catch (Exception e) {
                    e.printStackTrace();
                    logger.error("获取用户信息异常", e);
                    throw new SysException("[请求异常] OAuth获取用户信息，返回JSON异常: " + userInfoHttpResult);
                }
            }
        }
        if (userInfoJsonObject == null) {
            logger.error("获取用户信息失败:" + this.yghAppUrl + "/oauth/userInfo");
            throw new SysException("[请求异常] OAuth获取用户信息，返回JSON异常: " + userInfoHttpResult);
        }
        //调试代码
        logger.debug("2、请求获取的用户信息: " + userInfoHttpResult);
        JSONObject userInfoJson = userInfoJsonObject.getJSONObject("userInfo");
        //这里要缓存起用户信息
        if (userInfoJson == null) {
            logger.error("用户信息转json失败：userInfoJson = null");
            throw new SysException("[请求异常] OAuth获取用户信息，返回JSON中没有userInfo: " + userInfoHttpResult);
        }
        SycUserInfo sycUserInfo = JsonUtils.toJavaObject(userInfoJson, SycUserInfo.class);
        if (sycUserInfo == null) {
            throw new SysException("[getOauthUserInfo] OAuth获取用户信息，返回JSON中解析失败: " + userInfoHttpResult);
        }
        String openId = sycUserInfo.getOpenId();
        //用户的唯一标识，系统中唯一且不变
        //保存数据库操作
        logger.info("获取用户信息: " + JsonUtils.toStringNoEx(sycUserInfo));
        UserDO user = null;
        try {
            user = userService.insertUser(sycUserInfo);
        } catch (Exception e) {
            e.printStackTrace();
            throw new SysException("[请求异常] OAuth插入用户信息失败: " + e.getMessage());
        }
        //logger.error("结束保存或者更新用户数据>>> "+JsonUtils.toStringNoEx(obj));
        if (user == null) {
            logger.error("保存或者更新用户数据失败");
            return null;
        }
        UserSession us = new UserSession();
        us.setId(user.getId());
        us.setImgurl(user.getHeadImg());
        us.setUserName(user.getUserName());
        us.setToken(user.getOpenId());
        us.setNickName(sycUserInfo.getRealName());
        us.setRealName(user.getUserName());
        us.setPhoneNum(user.getUserPhone());

        String memberUnionCode = sycUserInfo.getMemberUnionCode();
        String unionNo = UnionUtils.unionFormat(memberUnionCode);
        us.setUnionNo(unionNo);
        if ("G".equals(sycUserInfo.getUserType())) {
            us.setKind(Constants.VIP_USER);    //VIP 1
        } else {
            us.setKind(Constants.DOMESTIC_USER);    //普通用户 0
        }

        try {
            logger.info("用户登录的UserSession== " + JsonUtils.toStringNoEx(us));

            cacheService.putUserSession(openId, us);
        } catch (Exception e) {
            logger.error("缓存登录信息失败: " + openId, e);
            throw new SysException("[请求异常] 缓存登录信息失败: " + e.getMessage());
        }
        return openId;
    }

    /**
     * 获取OAuth AccessToken 这个是应用的token
     *
     * @return
     */
    public String getOauthAccessToken() {
        StringBuilder sb = new StringBuilder();
        sb.append("clientId=").append(clientId).append("&clientSecret=").append(clientSecret);
        try {
            String url = yghAppUrl + "/oauth/accessToken?" + sb.toString();
            HttpResult hr = HttpUtils.getSSL(url, "utf-8", null);
            if (!hr.isSuccess()) {
                logger.error("[远程请求异常] OAuth获取accessToken，返回JSON解析异常");
                logger.error(hr.getHtml());
                return "";
            }
            hr.makeHtml("utf-8");
            JSONObject root = hr.asJSON();
            if (root == null) {
                logger.error("[远程请求异常] OAuth获取accessToken，返回JSON解析异常");
                logger.error(hr.getHtml());
                return "";
            }
            String accessToken = root.getString("access_token");
            redisCacheManager.getRedisTemplate().opsForValue().set(accessTokenKey, accessToken, ONE_DAY_SECOND, TimeUnit.SECONDS);
            return accessToken;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public String testOauth(String queryId) throws SysException {
        SycUserInfo sycUserInfo = new SycUserInfo();
        if (CommonUtils.isNotNull(queryId)) {
            sycUserInfo.setOpenId(queryId);
        } else {
            sycUserInfo.setOpenId(UUID.randomUUID().toString().replace("-", ""));
        }
        sycUserInfo.setIdCardNum("330206201604271440");
        sycUserInfo.setRealName("TED");
        sycUserInfo.setPhoneNum("15867885908");
        sycUserInfo.setPhoto("");
        sycUserInfo.setMemberUnionCode("");
        sycUserInfo.setUserType("N");

        String openId = sycUserInfo.getOpenId();
        //用户的唯一标识，系统中唯一且不变
        //保存数据库操作
        logger.info("获取用户信息: " + JsonUtils.toStringNoEx(sycUserInfo));
        UserDO user = null;
        try {
            user = userService.insertUser(sycUserInfo);
        } catch (Exception e) {
            e.printStackTrace();
            throw new SysException("[请求异常] OAuth插入用户信息失败: " + e.getMessage());
        }
        //logger.error("结束保存或者更新用户数据>>> "+JsonUtils.toStringNoEx(obj));
        if (user == null) {
            logger.error("保存或者更新用户数据失败");
            return null;
        }
        UserSession us = new UserSession();
        us.setId(user.getId());
        us.setImgurl(user.getHeadImg());
        us.setUserName(user.getUserName());
        us.setToken(user.getOpenId());
        us.setNickName(sycUserInfo.getRealName());
        us.setRealName(user.getUserName());
        us.setPhoneNum(user.getUserPhone());

        String memberUnionCode = sycUserInfo.getMemberUnionCode();
        String unionNo = UnionUtils.unionFormat(memberUnionCode);
        us.setUnionNo(unionNo);
        if ("G".equals(sycUserInfo.getUserType())) {
            us.setKind(Constants.VIP_USER);    //VIP 1
        } else {
            us.setKind(Constants.DOMESTIC_USER);    //普通用户 0
        }

        try {
            logger.info("用户登录的UserSession== " + JsonUtils.toStringNoEx(us));

            cacheService.putUserSession(openId, us);
        } catch (Exception e) {
            logger.error("缓存登录信息失败: " + openId, e);
            throw new SysException("[请求异常] 缓存登录信息失败: " + e.getMessage());
        }
        return openId;
    }
}
